home *** CD-ROM | disk | FTP | other *** search
- /* 006 13-Dec-86 ovvbuf.c
-
- Buffer management routines for ovview.c
-
- Copyright (c) 1986 by Blue Sky Software. All rights reserved.
- */
-
- #include <stdio.h>
- #include <fcntl.h>
- #include "ov.h"
-
- #define MAX_VBUF 8 /* allow up to 8 in memory buffers */
- #define VBUF_LEN 16*1024 /* a buffer is 16K - make a power of 2 */
-
- typedef struct { /* define the View BUFfer DEScriptior */
- int buflen;
- long bufoff;
- char far *bufp;
- } VBUF_DES;
-
- static int vidx; /* current VBUF descriptor in use */
- static int vlast; /* last VBUF descriptor in use */
- static int num_vbuf; /* highest buffer that can be alloc'd */
- static VBUF_DES vbufd[MAX_VBUF]; /* the arrary of VBUF descriptors */
- static long bufoff; /* offset in file of current buffer */
- static unsigned int buflen; /* length of data in current buffer */
- unsigned char far *bufp; /* begining of data in buffer */
- unsigned char far *curp; /* current char location in buffer */
- unsigned char far *endp; /* end of current buffer */
-
- /*global*/ int ALTCALL vbuf_init(int );
- /*global*/ int ALTCALL vbuf_free(void);
- /*global*/ unsigned long ALTCALL vtell(void);
- /*global*/ int ALTCALL vseek(int ,long );
- /*global*/ int ALTCALL vnextch(int );
- /*global*/ int ALTCALL vprevch(int );
- static int ALTCALL pagefwd(int ,long );
- static int ALTCALL pagebck(int ,long );
- static int ALTCALL vswitch(int );
-
-
- /*****************************************************************************
- V B U F _ I N I T
- *****************************************************************************/
-
- int ALTCALL
- vbuf_init(fh) /* initialize the buffer system */
- int fh;
- {
- vlast = -1; /* set indexes, etc to force an */
- num_vbuf = MAX_VBUF; /* so the initial read loads the */
- pagefwd(fh,0L); /* first buffer from the file */
- vswitch(0); /* make the 1st buffer active */
- curp = bufp; /* at the 1st char in 1st buffer */
- }
-
-
- /*****************************************************************************
- V B U F _ F R E E
- *****************************************************************************/
-
- int ALTCALL
- vbuf_free() { /* release all memory buffers */
-
- register int i;
- register VBUF_DES *vp;
-
- for (i = 0, vp = vbufd; i <= vlast; i++, vp++) { /* release all buffers */
- free_f(vp->bufp);
- vp->bufp = NULL;
- }
- }
-
-
- /****************************************************************************
- V T E L L
- ****************************************************************************/
-
- unsigned long ALTCALL
- vtell() { /* return file offset of current character */
-
- return(bufoff + (curp - bufp));
- }
-
-
- /*****************************************************************************
- V S E E K
- *****************************************************************************/
-
- int ALTCALL
- vseek(fh,offset) /* seek to specified offset in file/buffers */
- int fh;
- long offset;
- {
- register int i;
- long readoff, labs();
- register VBUF_DES *vp;
-
- /* "seek" is easy if offset is in current buffer - normal case I hope */
-
- if (offset >= bufoff && offset < bufoff + VBUF_LEN) {
-
- curp = bufp + (offset - bufoff);
- return;
-
- } else { /* not in current buffer, is it in any buffer? */
-
- for (i = 0, vp = vbufd; i <= vlast; i++, vp++)
- if (offset >= vp->bufoff && offset < vp->bufoff + VBUF_LEN) {
- vswitch(i); /* switch to buffer with */
- curp = bufp + (offset - bufoff); /* wanted offset */
- return;
- }
- }
-
- /* offset location isn't in memory, do it the old fashion way, read it */
-
- readoff = offset & ~((long)(VBUF_LEN-1)); /* where to read from */
-
- /* special case if seeking what would be the next or prev buffer, we
- keep as much buffered in memory as possible */
-
- if (labs(readoff - bufoff) == VBUF_LEN) { /* reading next or prev block? */
-
- if (readoff > bufoff) { /* next block? */
- pagefwd(fh,readoff); /* swap in next buffer */
- vswitch(vidx+1); /* make it active */
- } else { /* previous block */
- pagebck(fh,readoff); /* swap in prev buffer */
- vswitch(vidx-1); /* make it active */
- }
-
- } else { /* not reading next or prev buffer */
-
- /* seeking to some random position in file, discard all current buffers
- and start over from new position */
-
- vidx = vlast = 0; /* discard all buffers */
- vbufd[0].bufoff = bufoff = readoff; /* where to read from */
- bufp = vbufd[0].bufp; /* where to read to */
- l_seek(fh,readoff);
- vbufd[0].buflen = buflen = readbuf(fh,bufp,VBUF_LEN);
- endp = bufp + buflen;
- }
-
- curp = bufp + (offset - bufoff); /* got buffer, goto offset */
- return;
- }
-
-
- /****************************************************************************
- V N E X T C H
- ****************************************************************************/
-
- int ALTCALL
- vnextch(fh) /* return next character from file/buffers */
- int fh;
- {
- /************** Following code is duplicated by some callers **************/
-
- if (curp < endp) /* the normal case is just to return */
- return(*curp++); /* the next character in the buffer */
-
- /**************************************************************************/
-
- if (buflen < VBUF_LEN) /* only last buffer can be < VBUF_LEN */
- return(EOF);
-
- if (vidx == vlast) /* read more from file? */
- if (pagefwd(fh,bufoff+VBUF_LEN) == EOF) /* try paging into the file */
- return(EOF); /* watch for EOF */
-
- vswitch(vidx+1); /* switch to next buffer */
- curp = bufp; /* at start of buffer */
-
- return(*curp++); /* return 1st char in it */
- }
-
-
- /****************************************************************************
- V P R E V C H
- ****************************************************************************/
-
- int ALTCALL
- vprevch(fh) /* return previous character from file/buffers */
- int fh;
- {
- /************** Following code is duplicated by some callers **************/
-
- if (curp > bufp) /* the normal case is just to return */
- return(*--curp); /* the prev character in the buffer */
-
- /**************************************************************************/
-
- if (bufoff == 0) /* at top of file? (offset == 0) */
- return(EOF);
-
- if (vidx == 0) /* is this the oldest buffer? */
- pagebck(fh,bufoff-VBUF_LEN); /* if so, page backward a buffer */
-
- vswitch(vidx-1); /* switch to prev buffer */
- curp = endp; /* at end of buffer */
-
- return(*--curp); /* return last char in it */
- }
-
-
- /*****************************************************************************
- P A G E F W D
- *****************************************************************************/
-
- static int ALTCALL
- pagefwd(fh,offset) /* page forward into the file being read */
- int fh;
- long offset;
- {
- int i;
- register VBUF_DES *vp;
- char far *bp, far *malloc_f();
-
- /* bump the index of the last buffer used, check if all buffer
- descriptors are used, if so reuse the oldest, otherwise try
- to allocate another buffer and use that */
-
- getbuf: /* look ma, a label for a goto! */
-
- if (vlast == num_vbuf-1) { /* all buffer descriptors used? */
-
- bp = vbufd[0].bufp; /* remember where buffer is */
- for (i = 0; i < num_vbuf-1; i++) /* throw away oldest buffer by */
- vbufd[i] = vbufd[i+1]; /* moving others down over it */
- vbufd[vlast].bufp = bp; /* reuse oldest buffer */
- vidx--; /* descriptors were shifted 1 */
-
- } else { /* try to allocate another buffer */
-
- vlast++; /* move to the next descriptor */
-
- /* if we haven't already done so, allocate another buffer for the
- descriptor, failing that use a reduced number of buffers. We
- need to be able to alloc at least 1 */
-
- if (vbufd[vlast].bufp == NULL)
- if ((vbufd[vlast].bufp = malloc_f(VBUF_LEN)) == NULL) {
- if (vlast == 0)
- show_error(0,15,1,"No memory for view buffer");
- num_vbuf = vlast--; /* can't alloc another buffer, operate with */
- goto getbuf; /* a reduced number (minimum 1) of buffers */
- }
- }
-
- /* a descriptor/buffer is ready, fill it with data from the file */
-
- vp = &vbufd[vlast]; /* speed things up */
- l_seek(fh,vp->bufoff = offset); /* where to read from */
- vp->buflen = readbuf(fh,vp->bufp,VBUF_LEN);
-
- if (vp->buflen == 0) /* very unlikley, but maybe EOF */
- return(EOF);
- else
- return(1);
- }
-
-
- /*****************************************************************************
- P A G E B C K
- *****************************************************************************/
-
- static int ALTCALL
- pagebck(fh,offset) /* page backward into the file being read */
- int fh;
- long offset;
- {
- char far *bp;
- register int i;
-
- /* reuse the "newest" buffer (last one in descriptor array) */
-
- bp = vbufd[vlast].bufp; /* remember where buffer is */
- for (i = vlast; i > 0; i--) /* throw away newest buffer by */
- vbufd[i] = vbufd[i-1]; /* moving others over it */
-
- vbufd[0].bufp = bp; /* reuse newest buffer */
- vidx++; /* descriptors were shifted 1 */
-
- /* a descriptor/buffer is ready, fill it with data from the file */
-
- l_seek(fh,vbufd[0].bufoff = offset); /* where to read from */
- vbufd[0].buflen = readbuf(fh,bp,VBUF_LEN);
- }
-
-
- /*****************************************************************************
- V S W I T C H
- *****************************************************************************/
-
- static int ALTCALL
- vswitch(idx) /* make buffer idx the current buffer */
- int idx;
- {
- register VBUF_DES *vp;
-
- vp = &vbufd[vidx = idx]; /* assign vidx, address of vidx descriptor */
-
- bufp = vp->bufp; /* buffer location */
- bufoff = vp->bufoff; /* file offset of buffer */
- buflen = vp->buflen; /* len of data in buffer */
- endp = bufp + buflen; /* 1 past the last valid data byte in buffer */
- }